import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
// 添加拾取功能
import { Raycaster } from 'three';
// 其他加载器...

// 1. 初始化场景、相机、渲染器
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x333333);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.outputEncoding = THREE.sRGBEncoding;

document.body.appendChild(renderer.domElement);

// 添加轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;

// 添加光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);

// 体素化参数
let voxelSize = 0.1; // 使用 let 而非 const，因为这个值会被调整
let totalSurfaceArea = 0;
let model = null;
let modelSize = new THREE.Vector3(5, 5, 5); // 默认大小，防止初始相机位置错误

// 表面选择参数
let selectionMode = false;
let selectedFaces = new Set(); // 存储被选中的面
let raycaster = new THREE.Raycaster();
let mouse = new THREE.Vector2();
let selectedMeshes = []; // 存储被选中的网格
let highlightMaterial = new THREE.MeshBasicMaterial({
    color: 0x00ff00,
    transparent: true,
    opacity: 0.3,
    side: THREE.DoubleSide
});

// 创建UI
createUserInterface();

function createUserInterface() {
    const panel = document.createElement('div');
    panel.style.position = 'absolute';
    panel.style.top = '10px';
    panel.style.left = '10px';
    panel.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
    panel.style.padding = '10px';
    panel.style.borderRadius = '5px';
    panel.style.color = 'white';
    panel.style.fontFamily = 'Arial, sans-serif';
    panel.style.zIndex = '1000';
    
    // 标题
    const title = document.createElement('h3');
    title.textContent = '体素化模型表面积计算';
    title.style.margin = '0 0 10px 0';
    panel.appendChild(title);
    
    // 模型选择
    const fileInputContainer = document.createElement('div');
    fileInputContainer.style.marginBottom = '10px';
    
    const fileLabel = document.createElement('label');
    fileLabel.textContent = '选择模型文件 (.glb, .gltf): ';
    fileLabel.style.display = 'block';
    fileLabel.style.marginBottom = '5px';
    fileInputContainer.appendChild(fileLabel);
    
    const fileInput = document.createElement('input');
    fileInput.type = 'file';
    fileInput.accept = '.glb,.gltf';
    fileInput.style.marginBottom = '10px';
    fileInput.addEventListener('change', handleFileSelect);
    fileInputContainer.appendChild(fileInput);
    panel.appendChild(fileInputContainer);
    
    // 加载默认模型按钮
    const loadDefaultBtn = document.createElement('button');
    loadDefaultBtn.textContent = '加载示例模型';
    loadDefaultBtn.style.padding = '5px 10px';
    loadDefaultBtn.style.marginRight = '10px';
    loadDefaultBtn.addEventListener('click', loadDefaultModel);
    panel.appendChild(loadDefaultBtn);
    
    // 选择表面按钮
    const selectSurfaceBtn = document.createElement('button');
    selectSurfaceBtn.textContent = '开始选择表面';
    selectSurfaceBtn.style.padding = '5px 10px';
    selectSurfaceBtn.style.marginRight = '10px';
    selectSurfaceBtn.style.backgroundColor = '#2196F3';
    selectSurfaceBtn.style.color = 'white';
    selectSurfaceBtn.style.border = 'none';
    selectSurfaceBtn.style.borderRadius = '3px';
    selectSurfaceBtn.style.cursor = 'pointer';
    selectSurfaceBtn.addEventListener('click', toggleSelectionMode);
    panel.appendChild(selectSurfaceBtn);
    
    // 清除选择按钮
    const clearSelectionBtn = document.createElement('button');
    clearSelectionBtn.textContent = '清除选择';
    clearSelectionBtn.style.padding = '5px 10px';
    clearSelectionBtn.style.marginRight = '10px';
    clearSelectionBtn.style.backgroundColor = '#f44336';
    clearSelectionBtn.style.color = 'white';
    clearSelectionBtn.style.border = 'none';
    clearSelectionBtn.style.borderRadius = '3px';
    clearSelectionBtn.style.cursor = 'pointer';
    clearSelectionBtn.addEventListener('click', clearSelection);
    panel.appendChild(clearSelectionBtn);
    
    // 计算表面积按钮
    const calculateBtn = document.createElement('button');
    calculateBtn.textContent = '计算选中表面积';
    calculateBtn.style.padding = '5px 10px';
    calculateBtn.style.backgroundColor = '#4CAF50';
    calculateBtn.style.color = 'white';
    calculateBtn.style.border = 'none';
    calculateBtn.style.borderRadius = '3px';
    calculateBtn.style.cursor = 'pointer';
    calculateBtn.addEventListener('click', () => {
        if (model) {
            // 检查模型是否有效
            if (!isValidModel(model)) {
                alert('模型无效或数据不完整，请重新加载模型');
                return;
            }
            
            // 检查是否有选中的表面
            if (selectedMeshes.length === 0) {
                alert('请先选择模型表面');
                return;
            }
            
            // 清除现有体素可视化
            clearVoxels();
            
            // 重新计算体素化
            const surfaceArea = document.getElementById('surface-area');
            if (surfaceArea) {
                surfaceArea.textContent = '计算中...';
            }
            // 使用setTimeout让UI能够更新
            setTimeout(() => {
                try {
                    voxelizeSelectedSurface();
                } catch (error) {
                    console.error('体素化计算失败:', error);
                    if (surfaceArea) {
                        surfaceArea.textContent = '计算出错 - ' + error.message;
                    }
                    alert('体素化计算失败: ' + error.message);
                }
            }, 10);
        } else {
            alert('请先加载模型');
        }
    });
    panel.appendChild(calculateBtn);
    
    // 体素大小控制
    const voxelSizeContainer = document.createElement('div');
    voxelSizeContainer.style.marginTop = '10px';
    
    const voxelSizeLabel = document.createElement('label');
    voxelSizeLabel.textContent = '体素大小: ';
    voxelSizeLabel.style.display = 'block';
    voxelSizeLabel.style.marginBottom = '5px';
    voxelSizeContainer.appendChild(voxelSizeLabel);
    
    const voxelSizeSlider = document.createElement('input');
    voxelSizeSlider.type = 'range';
    voxelSizeSlider.min = '0.01';
    voxelSizeSlider.max = '0.5';
    voxelSizeSlider.step = '0.01';
    voxelSizeSlider.value = voxelSize.toString();
    voxelSizeSlider.style.width = '100%';
    voxelSizeSlider.addEventListener('input', function() {
        const value = parseFloat(this.value);
        voxelSizeValue.textContent = value.toFixed(2);
        updateVoxelSize(value);
    });
    voxelSizeContainer.appendChild(voxelSizeSlider);
    
    const voxelSizeValue = document.createElement('span');
    voxelSizeValue.textContent = voxelSize.toFixed(2);
    voxelSizeValue.style.marginLeft = '5px';
    voxelSizeContainer.appendChild(voxelSizeValue);
    
    panel.appendChild(voxelSizeContainer);
    
    // 选择模式状态显示
    const selectionStatusContainer = document.createElement('div');
    selectionStatusContainer.style.marginTop = '10px';
    selectionStatusContainer.style.padding = '5px';
    selectionStatusContainer.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
    selectionStatusContainer.style.borderRadius = '3px';
    
    const selectionStatus = document.createElement('div');
    selectionStatus.id = 'selection-status';
    selectionStatus.textContent = '选择模式: 关闭';
    selectionStatus.style.fontWeight = 'bold';
    selectionStatusContainer.appendChild(selectionStatus);
    
    const selectionHelp = document.createElement('div');
    selectionHelp.style.fontSize = '12px';
    selectionHelp.style.marginTop = '5px';
    selectionHelp.textContent = '选择模式下，点击模型表面高亮选择区域';
    selectionStatusContainer.appendChild(selectionHelp);
    
    panel.appendChild(selectionStatusContainer);
    
    // 结果显示区域
    const resultArea = document.createElement('div');
    resultArea.id = 'result-area';
    resultArea.style.marginTop = '15px';
    resultArea.style.padding = '10px';
    resultArea.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
    resultArea.style.borderRadius = '3px';
    resultArea.innerHTML = '<p>表面积: <span id="surface-area">未计算</span></p>';
    panel.appendChild(resultArea);
    
    // 加载进度
    const progressContainer = document.createElement('div');
    progressContainer.style.marginTop = '10px';
    progressContainer.style.display = 'none';
    progressContainer.id = 'loading-progress-container';
    
    const progressBar = document.createElement('div');
    progressBar.style.width = '100%';
    progressBar.style.height = '10px';
    progressBar.style.backgroundColor = '#444';
    progressBar.style.borderRadius = '5px';
    progressBar.style.overflow = 'hidden';
    
    const progressFill = document.createElement('div');
    progressFill.id = 'progress-fill';
    progressFill.style.width = '0%';
    progressFill.style.height = '100%';
    progressFill.style.backgroundColor = '#4CAF50';
    progressFill.style.transition = 'width 0.2s';
    
    progressBar.appendChild(progressFill);
    progressContainer.appendChild(progressBar);
    
    const progressText = document.createElement('div');
    progressText.id = 'progress-text';
    progressText.style.textAlign = 'center';
    progressText.style.marginTop = '5px';
    progressText.textContent = '0%';
    progressContainer.appendChild(progressText);
    
    panel.appendChild(progressContainer);
    
    document.body.appendChild(panel);
}

function handleFileSelect(event) {
    const file = event.target.files[0];
    if (file) {
        const url = URL.createObjectURL(file);
        loadModel(url, file.name);
    }
}

function loadDefaultModel() {
    // 使用默认示例模型 (假设在模型目录中)
    try {
        loadModel('./static/hamburger.glb', 'hamburger.glb');
    } catch (error) {
        console.error('加载默认模型失败:', error);
        alert('无法加载默认模型，请确保models目录中有example.glb文件');
    }
}

function updateVoxelSize(size) {
    voxelSize = size;
    // 不再自动计算，只更新参数值
    const surfaceArea = document.getElementById('surface-area');
    if (surfaceArea) {
        surfaceArea.textContent = '请点击"计算表面积"按钮';
    }
}

function loadModel(url, filename) {
    console.log('开始加载模型:', url);
    
    // 获取进度条相关元素前先检查它们是否存在
    const progressContainer = document.getElementById('loading-progress-container');
    const progressFill = document.getElementById('progress-fill');
    const progressText = document.getElementById('progress-text');
    const surfaceArea = document.getElementById('surface-area');
    
    // 安全地显示进度条
    if (progressContainer) {
        progressContainer.style.display = 'block';
    } else {
        console.warn('进度条容器未找到');
    }
    
    // 安全地更新表面积显示
    if (surfaceArea) {
        surfaceArea.textContent = '加载中...';
    } else {
        console.warn('表面积显示元素未找到');
    }
    
    // 清除现有模型和体素
    if (model) {
        scene.remove(model);
        // 清除体素可视化
        scene.traverse((object) => {
            if (object.userData && object.userData.isVoxel) {
                scene.remove(object);
            }
        });
    }
    
    totalSurfaceArea = 0;
    
    // 加载新模型
    const loader = new GLTFLoader();
    
    loader.load(
        url, 
        (gltf) => {
            model = gltf.scene;
            
            // 重置模型变换
            model.position.set(0, 0, 0);
            model.rotation.set(0, 0, 0);
            model.scale.set(1, 1, 1);
            
            // 居中模型
            const box = new THREE.Box3().setFromObject(model);
            
            // 检查模型包围盒是否有效
            if (!isBoxValid(box)) {
                console.error('模型包围盒无效', box);
                if (surfaceArea) {
                    surfaceArea.textContent = '无效模型 - 请检查模型文件';
                }
                if (progressContainer) {
                    progressContainer.style.display = 'none';
                }
                return;
            }
            
            const center = new THREE.Vector3();
            box.getCenter(center);
            model.position.sub(center);
            
            // 缩放模型以适应视图
            box.setFromObject(model); // 重新计算
            const size = new THREE.Vector3();
            box.getSize(size);
            modelSize = size.clone();
            
            // 检查模型是否太小
            const minDim = Math.min(size.x, size.y, size.z);
            if (minDim < 0.01) {
                console.warn('模型尺寸过小，进行放大', size);
                // 放大模型，确保最小尺寸至少为1
                const scaleFactor = 1 / minDim;
                model.scale.multiplyScalar(scaleFactor);
                // 更新尺寸和包围盒
                box.setFromObject(model);
                box.getSize(modelSize);
                console.log('调整后的模型尺寸:', modelSize);
            }
            
            const maxDim = Math.max(modelSize.x, modelSize.y, modelSize.z);
            if (maxDim > 10) {
                const scale = 10 / maxDim;
                model.scale.multiplyScalar(scale);
                // 重新计算包围盒和大小
                box.setFromObject(model);
                box.getSize(modelSize);
            }
            
            // 自动调整体素大小以匹配模型
            let recommendedVoxelSize = Math.min(
                modelSize.x, modelSize.y, modelSize.z
            ) / 20; // 建议每个维度至少20个体素
            
            voxelSize = Math.max(0.02, Math.min(0.2, recommendedVoxelSize));
            console.log(`根据模型自动调整体素大小为: ${voxelSize.toFixed(4)}`);
            
            // 更新UI上的体素大小滑块
            const sizeSlider = document.querySelector('input[type="range"]');
            if (sizeSlider) {
                sizeSlider.value = voxelSize;
                const sizeValueSpan = sizeSlider.nextElementSibling;
                if (sizeValueSpan) {
                    sizeValueSpan.textContent = voxelSize.toFixed(2);
                }
            }
            
            scene.add(model);
            
            // 调整相机位置
            const maxSize = Math.max(modelSize.x, modelSize.y, modelSize.z);
            camera.position.set(maxSize * 2, maxSize * 2, maxSize * 2);
            camera.lookAt(0, 0, 0);
            controls.update();
            
            // 提示用户计算表面积
            if (surfaceArea) {
                surfaceArea.textContent = '请点击"计算表面积"按钮';
            }
            
            // 隐藏进度条
            if (progressContainer) {
                progressContainer.style.display = 'none';
            }
            
            console.log(`模型 ${filename} 加载完成`);
        },
        (xhr) => {
            if (xhr.lengthComputable && progressFill && progressText) {
                const progress = xhr.loaded / xhr.total * 100;
                progressFill.style.width = `${progress}%`;
                progressText.textContent = `${Math.round(progress)}%`;
            }
        },
        (error) => {
            console.error('模型加载失败:', error);
            if (surfaceArea) {
                surfaceArea.textContent = '加载失败';
            }
            if (progressContainer) {
                progressContainer.style.display = 'none';
            }
            
            // 显示错误消息
            alert(`模型加载失败: ${error.message}`);
        }
    );
}

// 检查包围盒是否有效（没有NaN或Infinity值）
function isBoxValid(box) {
    // 检查最小点
    if (isNaN(box.min.x) || isNaN(box.min.y) || isNaN(box.min.z) ||
        !isFinite(box.min.x) || !isFinite(box.min.y) || !isFinite(box.min.z)) {
        return false;
    }
    
    // 检查最大点
    if (isNaN(box.max.x) || isNaN(box.max.y) || isNaN(box.max.z) ||
        !isFinite(box.max.x) || !isFinite(box.max.y) || !isFinite(box.max.z)) {
        return false;
    }
    
    // 检查包围盒尺寸是否为0或负数
    const size = new THREE.Vector3();
    box.getSize(size);
    if (size.x <= 0 || size.y <= 0 || size.z <= 0) {
        return false;
    }
    
    return true;
}

function voxelizeModel(model) {
    console.log('开始体素化模型...');
    
    // 再次检查模型有效性
    if (!isValidModel(model)) {
        throw new Error('无效的模型数据');
    }
    
    // 获取结果显示元素
    const surfaceArea = document.getElementById('surface-area');
    
    // 计算模型的包围盒
    const boundingBox = new THREE.Box3().setFromObject(model);
    
    // 确保包围盒有效
    if (!isBoxValid(boundingBox)) {
        console.error('模型包围盒无效，无法体素化');
        if (surfaceArea) {
            surfaceArea.textContent = '无效模型 - 无法计算';
        }
        return;
    }
    
    const modelSize = new THREE.Vector3();
    boundingBox.getSize(modelSize);
    
    console.log('模型尺寸:', modelSize);
    console.log('体素大小:', voxelSize);

    // 确保体素大小适合模型
    const minModelDim = Math.min(modelSize.x, modelSize.y, modelSize.z);
    if (voxelSize > minModelDim / 2) {
        // 体素过大，自动调整
        voxelSize = minModelDim / 5;
        console.log(`体素大小过大，自动调整为: ${voxelSize.toFixed(4)}`);
    }

    // 初始化体素网格
    const gridSizeX = Math.max(2, Math.ceil(modelSize.x / voxelSize));
    const gridSizeY = Math.max(2, Math.ceil(modelSize.y / voxelSize));
    const gridSizeZ = Math.max(2, Math.ceil(modelSize.z / voxelSize));

    // voxelGrid[x][y][z] = true 表示该体素被占据
    const voxelGrid = new Array(gridSizeX).fill(null)
                        .map(() => new Array(gridSizeY).fill(null)
                        .map(() => new Array(gridSizeZ).fill(false)));

    console.log(`网格尺寸: ${gridSizeX}x${gridSizeY}x${gridSizeZ}`);
    
    let triangleCount = 0;
    let processedTriangles = 0;
    let invalidTriangles = 0;
    
    // 使用体素采样方法而不是三角形相交测试
    console.log('采用体素采样方法进行体素化...');
    
    // 尝试使用简化的体素化方法
    const simplifiedVoxelization = true;
    
    if (simplifiedVoxelization) {
        // 简化体素化：对整个模型进行包围盒体素化
        console.log('使用简化体素化方法');
        
        // 创建模型的八叉树（或使用Three.js几何体体素化的直接方法）
        // 这里我们用一个简单的方法：对模型表面进行采样
        
        // 对每个网格进行体素化
        model.traverse((object) => {
            if (object.isMesh) {
                const geometry = object.geometry;
                
                // 确保几何体已处理
                geometry.computeBoundingBox();
                if (!geometry.attributes.normal) {
                    geometry.computeVertexNormals();
                }
                
                // 采样方法：对模型的每个点进行体素化
                const positions = geometry.attributes.position;
                const matrixWorld = object.matrixWorld;
                
                for (let i = 0; i < positions.count; i++) {
                    const vertex = new THREE.Vector3().fromBufferAttribute(positions, i);
                    vertex.applyMatrix4(matrixWorld); // 转换到世界坐标
                    
                    // 计算该顶点对应的体素坐标
                    const voxelX = Math.floor((vertex.x - boundingBox.min.x) / voxelSize);
                    const voxelY = Math.floor((vertex.y - boundingBox.min.y) / voxelSize);
                    const voxelZ = Math.floor((vertex.z - boundingBox.min.z) / voxelSize);
                    
                    // 检查是否在有效范围内
                    if (voxelX >= 0 && voxelX < gridSizeX &&
                        voxelY >= 0 && voxelY < gridSizeY &&
                        voxelZ >= 0 && voxelZ < gridSizeZ) {
                        voxelGrid[voxelX][voxelY][voxelZ] = true;
                    }
                }
                
                // 如果模型太稀疏，可以在顶点之间添加额外的采样点
                // 特别是当三角形较大时
                
                // 对三角形的边和内部进行采样以填补可能的空洞
                if (geometry.index) {
                    const indices = geometry.index.array;
                    
                    for (let i = 0; i < indices.length; i += 3) {
                        const idx1 = indices[i];
                        const idx2 = indices[i + 1];
                        const idx3 = indices[i + 2];
                        
                        // 获取三角形的三个顶点
                        const v1 = new THREE.Vector3().fromBufferAttribute(positions, idx1);
                        const v2 = new THREE.Vector3().fromBufferAttribute(positions, idx2);
                        const v3 = new THREE.Vector3().fromBufferAttribute(positions, idx3);
                        
                        // 转换到世界坐标
                        v1.applyMatrix4(matrixWorld);
                        v2.applyMatrix4(matrixWorld);
                        v3.applyMatrix4(matrixWorld);
                        
                        // 在三角形边上进行采样
                        sampleLine(v1, v2, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                        sampleLine(v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                        sampleLine(v3, v1, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                        
                        // 在三角形内部进行采样
                        sampleTriangleInterior(v1, v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                    }
                } else {
                    // 非索引几何体
                    for (let i = 0; i < positions.count; i += 3) {
                        const v1 = new THREE.Vector3().fromBufferAttribute(positions, i);
                        const v2 = new THREE.Vector3().fromBufferAttribute(positions, i + 1);
                        const v3 = new THREE.Vector3().fromBufferAttribute(positions, i + 2);
                        
                        // 转换到世界坐标
                        v1.applyMatrix4(matrixWorld);
                        v2.applyMatrix4(matrixWorld);
                        v3.applyMatrix4(matrixWorld);
                        
                        // 在三角形边上进行采样
                        sampleLine(v1, v2, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                        sampleLine(v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                        sampleLine(v3, v1, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                        
                        // 在三角形内部进行采样
                        sampleTriangleInterior(v1, v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                    }
                }
            }
        });
        
    } else {
        // 原始三角形相交测试方法
        model.traverse((object) => {
            if (object.isMesh) {
                console.log(`处理网格: ${object.name || 'unnamed'}`);
                const geometry = object.geometry;
                geometry.computeBoundingBox(); // 确保几何体有边界盒
                
                // 确保几何体已被完全处理
                if (!geometry.attributes.normal) {
                    geometry.computeVertexNormals();
                }
                
                // 获取变换矩阵
                const matrixWorld = object.matrixWorld;
                
                const positionAttribute = geometry.getAttribute('position');
                const indexAttribute = geometry.getIndex();

                if (positionAttribute) {
                    console.log(`顶点数量: ${positionAttribute.count}`);
                    
                    const vertices = [];
                    for (let i = 0; i < positionAttribute.count; i++) {
                        const vertex = new THREE.Vector3().fromBufferAttribute(positionAttribute, i);
                        vertex.applyMatrix4(matrixWorld); // 使用矩阵转换到世界坐标
                        vertices.push(vertex);
                    }

                    if (indexAttribute) { // 处理索引几何体
                        console.log(`索引数量: ${indexAttribute.count}`);
                        triangleCount += indexAttribute.count / 3;
                        
                        for (let i = 0; i < indexAttribute.count; i += 3) {
                            const vA = vertices[indexAttribute.getX(i)];
                            const vB = vertices[indexAttribute.getX(i + 1)];
                            const vC = vertices[indexAttribute.getX(i + 2)];
                            
                            // 检查三角形是否有效
                            if (isValidTriangle(vA, vB, vC)) {
                                const triangle = new THREE.Triangle(vA, vB, vC);
                                voxelizeTriangle(triangle, boundingBox.min, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                                processedTriangles++;
                            }
                        }
                    } else { // 处理非索引几何体
                        console.log(`非索引几何体，顶点数量: ${vertices.length}`);
                        triangleCount += Math.floor(vertices.length / 3);
                        
                        for (let i = 0; i < vertices.length; i += 3) {
                            if (i + 2 < vertices.length) {
                                const vA = vertices[i];
                                const vB = vertices[i + 1];
                                const vC = vertices[i + 2];
                                
                                // 检查三角形是否有效
                                if (isValidTriangle(vA, vB, vC)) {
                                    const triangle = new THREE.Triangle(vA, vB, vC);
                                    voxelizeTriangle(triangle, boundingBox.min, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                                    processedTriangles++;
                                }
                            }
                        }
                    }
                }
            }
        });
    }
    
    console.log(`处理了 ${processedTriangles} 个三角形，共 ${triangleCount} 个`);
    if (invalidTriangles > 0) {
        console.warn(`发现 ${invalidTriangles} 个无效三角形`);
    }
    
    // 检查是否有任何体素被标记
    let markedVoxels = 0;
    for (let x = 0; x < gridSizeX; x++) {
        for (let y = 0; y < gridSizeY; y++) {
            for (let z = 0; z < gridSizeZ; z++) {
                if (voxelGrid[x][y][z]) {
                    markedVoxels++;
                }
            }
        }
    }
    
    console.log(`被标记的体素数量: ${markedVoxels}`);
    
    if (markedVoxels === 0) {
        // 如果没有体素被标记，尝试更小的体素大小
        if (voxelSize > 0.05) {
            console.warn('没有体素被标记，尝试更小的体素大小...');
            voxelSize = voxelSize / 2;
            if (surfaceArea) {
                surfaceArea.textContent = '重新计算中...';
            }
            setTimeout(() => {
                voxelizeModel(model);
            }, 10);
            return;
        } else {
            console.error('体素化失败：没有体素被标记');
            if (surfaceArea) {
                surfaceArea.textContent = '计算失败 - 模型可能有问题';
            }
            return;
        }
    }

    // 识别表面体素并计算表面积
    const voxelFaceArea = voxelSize * voxelSize;
    const surfaceVoxelsMaterial = new THREE.MeshBasicMaterial({ 
        color: 0x00ff00, 
        wireframe: true,
        transparent: true,
        opacity: 0.7
    });

    totalSurfaceArea = 0; // 重置表面积计算
    let surfaceVoxelCount = 0;
    
    for (let x = 0; x < gridSizeX; x++) {
        for (let y = 0; y < gridSizeY; y++) {
            for (let z = 0; z < gridSizeZ; z++) {
                if (voxelGrid[x][y][z]) {
                    // 检查六个邻居
                    const neighbors = [
                        [x + 1, y, z], [x - 1, y, z],
                        [x, y + 1, z], [x, y - 1, z],
                        [x, y, z + 1], [x, y, z - 1]
                    ];

                    let isSurfaceVoxel = false;
                    let exposedFaces = 0;
                    for (const [nx, ny, nz] of neighbors) {
                        if (
                            nx < 0 || nx >= gridSizeX ||
                            ny < 0 || ny >= gridSizeY ||
                            nz < 0 || nz >= gridSizeZ ||
                            !voxelGrid[nx][ny][nz] // 如果邻居是空的
                        ) {
                            exposedFaces++;
                            isSurfaceVoxel = true; // 只要有一个面暴露，就认为是表面体素
                        }
                    }
                    
                    totalSurfaceArea += exposedFaces * voxelFaceArea;

                    if (isSurfaceVoxel) { // 可视化表面体素
                        surfaceVoxelCount++;
                        const voxelGeometry = new THREE.BoxGeometry(voxelSize, voxelSize, voxelSize);
                        const voxelMesh = new THREE.Mesh(voxelGeometry, surfaceVoxelsMaterial);
                        voxelMesh.position.set(
                            boundingBox.min.x + (x + 0.5) * voxelSize,
                            boundingBox.min.y + (y + 0.5) * voxelSize,
                            boundingBox.min.z + (z + 0.5) * voxelSize
                        );
                        voxelMesh.userData.isVoxel = true; // 标记为体素，方便后续清除
                        scene.add(voxelMesh);
                    }
                }
            }
        }
    }
    
    console.log(`表面体素数量: ${surfaceVoxelCount}`);
    console.log(`计算出的表面积: ${totalSurfaceArea.toFixed(4)}`);

    // 更新界面显示
    if (surfaceArea) {
        surfaceArea.textContent = `${totalSurfaceArea.toFixed(4)} 单位²`;
    }
}

// 检查三角形是否有效（不是退化的）
function isValidTriangle(v1, v2, v3) {
    // 检查三个点是否不同
    if (v1.equals(v2) || v2.equals(v3) || v3.equals(v1)) {
        return false;
    }
    
    // 计算两条边
    const edge1 = new THREE.Vector3().subVectors(v2, v1);
    const edge2 = new THREE.Vector3().subVectors(v3, v1);
    
    // 检查两条边是否不共线（通过叉积）
    const crossProduct = new THREE.Vector3().crossVectors(edge1, edge2);
    const crossProductLength = crossProduct.length();
    
    // 如果叉积长度接近0，则三角形退化（共线或面积极小）
    return crossProductLength > 1e-10;
}

function voxelizeTriangle(triangle, gridOrigin, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ) {
    // 首先验证三角形的每个顶点
    if (!isValidPoint(triangle.a) || !isValidPoint(triangle.b) || !isValidPoint(triangle.c)) {
        console.warn('三角形包含无效顶点', {
            a: triangle.a,
            b: triangle.b,
            c: triangle.c
        });
        return;
    }

    // 计算三角形的包围盒
    const triangleBoundingBox = new THREE.Box3();
    triangleBoundingBox.setFromArray([
        triangle.a.toArray(),
        triangle.b.toArray(),
        triangle.c.toArray()
    ]);
    
    // 验证三角形包围盒
    if (!isBoxValid(triangleBoundingBox)) {
        console.warn('三角形包围盒无效');
        return;
    }
    
    // 确定哪些体素需要检查（转换为体素网格坐标）
    const minVoxel = new THREE.Vector3(
        Math.floor((triangleBoundingBox.min.x - gridOrigin.x) / voxelSize),
        Math.floor((triangleBoundingBox.min.y - gridOrigin.y) / voxelSize),
        Math.floor((triangleBoundingBox.min.z - gridOrigin.z) / voxelSize)
    );
    
    const maxVoxel = new THREE.Vector3(
        Math.ceil((triangleBoundingBox.max.x - gridOrigin.x) / voxelSize),
        Math.ceil((triangleBoundingBox.max.y - gridOrigin.y) / voxelSize),
        Math.ceil((triangleBoundingBox.max.z - gridOrigin.z) / voxelSize)
    );
    
    // 验证计算的体素坐标是否有效
    if (!isValidPoint(minVoxel) || !isValidPoint(maxVoxel)) {
        console.warn('计算的体素坐标无效', {
            triangleBoundingBox,
            gridOrigin,
            voxelSize,
            minVoxel,
            maxVoxel
        });
        return;
    }
    
    // 限制在网格范围内
    minVoxel.x = Math.max(0, Math.min(gridSizeX - 1, minVoxel.x));
    minVoxel.y = Math.max(0, Math.min(gridSizeY - 1, minVoxel.y));
    minVoxel.z = Math.max(0, Math.min(gridSizeZ - 1, minVoxel.z));
    
    maxVoxel.x = Math.max(0, Math.min(gridSizeX - 1, maxVoxel.x));
    maxVoxel.y = Math.max(0, Math.min(gridSizeY - 1, maxVoxel.y));
    maxVoxel.z = Math.max(0, Math.min(gridSizeZ - 1, maxVoxel.z));
    
    // 遍历可能与三角形相交的体素
    for (let x = minVoxel.x; x <= maxVoxel.x; x++) {
        for (let y = minVoxel.y; y <= maxVoxel.y; y++) {
            for (let z = minVoxel.z; z <= maxVoxel.z; z++) {
                // 创建体素的AABB盒
                const voxelBox = new THREE.Box3(
                    new THREE.Vector3(
                        gridOrigin.x + x * voxelSize,
                        gridOrigin.y + y * voxelSize,
                        gridOrigin.z + z * voxelSize
                    ),
                    new THREE.Vector3(
                        gridOrigin.x + (x + 1) * voxelSize,
                        gridOrigin.y + (y + 1) * voxelSize,
                        gridOrigin.z + (z + 1) * voxelSize
                    )
                );
                
                // 检查三角形与体素是否相交
                if (triangleIntersectsBox(triangle, voxelBox)) {
                    voxelGrid[x][y][z] = true;
                }
            }
        }
    }
}

// 检查三角形是否与AABB盒相交
function triangleIntersectsBox(triangle, box) {
    // 1. 检查三角形的任意顶点是否在盒子内部
    if (box.containsPoint(triangle.a) || 
        box.containsPoint(triangle.b) || 
        box.containsPoint(triangle.c)) {
        return true;
    }
    
    // 2. 检查三角形的边是否与盒子相交
    const edges = [
        [triangle.a, triangle.b],
        [triangle.b, triangle.c],
        [triangle.c, triangle.a]
    ];
    
    // 盒子的六个面
    const boxPlanes = [
        // 下面 (y-min)
        { normal: new THREE.Vector3(0, -1, 0), point: new THREE.Vector3(0, box.min.y, 0) },
        // 上面 (y-max)
        { normal: new THREE.Vector3(0, 1, 0), point: new THREE.Vector3(0, box.max.y, 0) },
        // 左面 (x-min)
        { normal: new THREE.Vector3(-1, 0, 0), point: new THREE.Vector3(box.min.x, 0, 0) },
        // 右面 (x-max)
        { normal: new THREE.Vector3(1, 0, 0), point: new THREE.Vector3(box.max.x, 0, 0) },
        // 后面 (z-min)
        { normal: new THREE.Vector3(0, 0, -1), point: new THREE.Vector3(0, 0, box.min.z) },
        // 前面 (z-max)
        { normal: new THREE.Vector3(0, 0, 1), point: new THREE.Vector3(0, 0, box.max.z) }
    ];
    
    for (const edge of edges) {
        const line = new THREE.Line3(edge[0], edge[1]);
        
        // 检查线段是否与任何盒子面相交
        for (const plane of boxPlanes) {
            const intersection = new THREE.Vector3();
            const ray = new THREE.Ray(edge[0], new THREE.Vector3().subVectors(edge[1], edge[0]).normalize());
            
            // 计算射线与平面的交点
            const denominator = plane.normal.dot(ray.direction);
            
            if (Math.abs(denominator) > 0.0001) { // 非平行
                const t = plane.normal.dot(new THREE.Vector3().subVectors(plane.point, ray.origin)) / denominator;
                
                if (t >= 0 && t <= line.distance()) { // 在线段范围内
                    ray.at(t, intersection);
                    
                    // 检查交点是否在盒子面内
                    if (intersection.x >= box.min.x && intersection.x <= box.max.x &&
                        intersection.y >= box.min.y && intersection.y <= box.max.y &&
                        intersection.z >= box.min.z && intersection.z <= box.max.z) {
                        return true;
                    }
                }
            }
        }
    }
    
    // 3. 检查盒子的边是否穿过三角形
    // 盒子的12条边
    const boxEdges = [
        // 底部四边
        [new THREE.Vector3(box.min.x, box.min.y, box.min.z), new THREE.Vector3(box.max.x, box.min.y, box.min.z)],
        [new THREE.Vector3(box.max.x, box.min.y, box.min.z), new THREE.Vector3(box.max.x, box.min.y, box.max.z)],
        [new THREE.Vector3(box.max.x, box.min.y, box.max.z), new THREE.Vector3(box.min.x, box.min.y, box.max.z)],
        [new THREE.Vector3(box.min.x, box.min.y, box.max.z), new THREE.Vector3(box.min.x, box.min.y, box.min.z)],
        // 顶部四边
        [new THREE.Vector3(box.min.x, box.max.y, box.min.z), new THREE.Vector3(box.max.x, box.max.y, box.min.z)],
        [new THREE.Vector3(box.max.x, box.max.y, box.min.z), new THREE.Vector3(box.max.x, box.max.y, box.max.z)],
        [new THREE.Vector3(box.max.x, box.max.y, box.max.z), new THREE.Vector3(box.min.x, box.max.y, box.max.z)],
        [new THREE.Vector3(box.min.x, box.max.y, box.max.z), new THREE.Vector3(box.min.x, box.max.y, box.min.z)],
        // 连接顶部和底部的四条边
        [new THREE.Vector3(box.min.x, box.min.y, box.min.z), new THREE.Vector3(box.min.x, box.max.y, box.min.z)],
        [new THREE.Vector3(box.max.x, box.min.y, box.min.z), new THREE.Vector3(box.max.x, box.max.y, box.min.z)],
        [new THREE.Vector3(box.max.x, box.min.y, box.max.z), new THREE.Vector3(box.max.x, box.max.y, box.max.z)],
        [new THREE.Vector3(box.min.x, box.min.y, box.max.z), new THREE.Vector3(box.min.x, box.max.y, box.max.z)]
    ];
    
    // 创建三角形平面
    const triangleNormal = new THREE.Vector3();
    triangle.getNormal(triangleNormal);
    const trianglePlane = {
        normal: triangleNormal,
        point: triangle.a
    };
    
    for (const edge of boxEdges) {
        const line = new THREE.Line3(edge[0], edge[1]);
        const ray = new THREE.Ray(edge[0], new THREE.Vector3().subVectors(edge[1], edge[0]).normalize());
        const intersection = new THREE.Vector3();
        
        // 计算射线与三角形平面的交点
        const denominator = trianglePlane.normal.dot(ray.direction);
        
        if (Math.abs(denominator) > 0.0001) { // 非平行
            const t = trianglePlane.normal.dot(new THREE.Vector3().subVectors(trianglePlane.point, ray.origin)) / denominator;
            
            if (t >= 0 && t <= line.distance()) { // 在线段范围内
                ray.at(t, intersection);
                
                // 检查交点是否在三角形内部
                if (triangle.containsPoint(intersection)) {
                    return true;
                }
            }
        }
    }
    
    return false;
}

// 检查点是否有效（不含NaN或Infinity）
function isValidPoint(point) {
    return point && 
           !isNaN(point.x) && !isNaN(point.y) && !isNaN(point.z) &&
           isFinite(point.x) && isFinite(point.y) && isFinite(point.z);
}

// 窗口大小调整处理
window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

// 渲染循环
function animate() {
    requestAnimationFrame(animate);
    controls.update();
    renderer.render(scene, camera);
}
animate();

// 加载默认模型提示
console.log('请选择模型文件或加载示例模型进行体素化');

// 在两点之间的线段上采样
function sampleLine(start, end, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ) {
    // 计算线段长度和方向
    const direction = new THREE.Vector3().subVectors(end, start);
    const length = direction.length();
    direction.normalize();
    
    // 计算采样点数量（确保每个体素至少有一个采样点）
    const sampleCount = Math.max(2, Math.ceil(length / (voxelSize * 0.5)));
    
    // 在线段上采样点
    for (let i = 0; i <= sampleCount; i++) {
        const t = i / sampleCount;
        const point = new THREE.Vector3().copy(start).lerp(end, t);
        
        // 计算对应的体素坐标
        const voxelX = Math.floor((point.x - boundingBox.min.x) / voxelSize);
        const voxelY = Math.floor((point.y - boundingBox.min.y) / voxelSize);
        const voxelZ = Math.floor((point.z - boundingBox.min.z) / voxelSize);
        
        // 检查是否在有效范围内
        if (voxelX >= 0 && voxelX < gridSizeX &&
            voxelY >= 0 && voxelY < gridSizeY &&
            voxelZ >= 0 && voxelZ < gridSizeZ) {
            voxelGrid[voxelX][voxelY][voxelZ] = true;
        }
    }
}

// 采样三角形内部
function sampleTriangleInterior(v1, v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ) {
    // 计算三角形的包围盒
    const triBox = new THREE.Box3();
    triBox.expandByPoint(v1);
    triBox.expandByPoint(v2);
    triBox.expandByPoint(v3);
    
    // 避免过于密集的采样
    const triSize = new THREE.Vector3();
    triBox.getSize(triSize);
    const maxSize = Math.max(triSize.x, triSize.y, triSize.z);
    
    // 如果三角形太小，跳过内部采样
    if (maxSize < voxelSize) {
        return;
    }
    
    // 对较大的三角形进行内部采样
    // 使用Barycentric坐标进行均匀采样
    const sampleCount = Math.ceil(maxSize / voxelSize);
    
    for (let i = 0; i < sampleCount; i++) {
        for (let j = 0; j < sampleCount - i; j++) {
            // Barycentric坐标
            const u = i / sampleCount;
            const v = j / sampleCount;
            const w = 1 - u - v;
            
            // 如果坐标有效
            if (u >= 0 && v >= 0 && w >= 0) {
                // 计算三角形内部的点
                const point = new THREE.Vector3()
                    .addScaledVector(v1, u)
                    .addScaledVector(v2, v)
                    .addScaledVector(v3, w);
                
                // 计算对应的体素坐标
                const voxelX = Math.floor((point.x - boundingBox.min.x) / voxelSize);
                const voxelY = Math.floor((point.y - boundingBox.min.y) / voxelSize);
                const voxelZ = Math.floor((point.z - boundingBox.min.z) / voxelSize);
                
                // 检查是否在有效范围内
                if (voxelX >= 0 && voxelX < gridSizeX &&
                    voxelY >= 0 && voxelY < gridSizeY &&
                    voxelZ >= 0 && voxelZ < gridSizeZ) {
                    voxelGrid[voxelX][voxelY][voxelZ] = true;
                }
            }
        }
    }
}

// 清除场景中的体素可视化
function clearVoxels() {
    // 使用安全的方式删除体素
    const voxelsToRemove = [];
    
    // 先收集要删除的对象
    scene.traverse((object) => {
        if (object.userData && object.userData.isVoxel) {
            voxelsToRemove.push(object);
        }
    });
    
    // 然后删除它们
    for (const voxel of voxelsToRemove) {
        scene.remove(voxel);
    }
    
    // 如果有大量对象，可能需要手动释放内存
    if (voxelsToRemove.length > 1000) {
        // 提示垃圾回收器（虽然不保证立即执行）
        setTimeout(() => {
            if (typeof window.gc === 'function') {
                window.gc();
            }
        }, 100);
    }
}

// 检查模型是否有效
function isValidModel(model) {
    // 检查模型是否为undefined或null
    if (!model) return false;
    
    // 检查traverse方法
    if (typeof model.traverse !== 'function') {
        console.error('模型缺少traverse方法');
        return false;
    }
    
    // 检查模型是否有任何网格
    let hasMesh = false;
    try {
        model.traverse((object) => {
            if (object.isMesh) {
                hasMesh = true;
            }
        });
    } catch (error) {
        console.error('模型遍历失败:', error);
        return false;
    }
    
    if (!hasMesh) {
        console.warn('模型不包含任何网格');
    }
    
    return true;
}

// 切换表面选择模式
function toggleSelectionMode() {
    selectionMode = !selectionMode;
    
    // 更新UI状态
    const statusElement = document.getElementById('selection-status');
    if (statusElement) {
        statusElement.textContent = `选择模式: ${selectionMode ? '开启' : '关闭'}`;
        statusElement.style.color = selectionMode ? '#4CAF50' : 'white';
    }
    
    // 如果开启选择模式，添加点击事件监听
    if (selectionMode) {
        renderer.domElement.addEventListener('click', handleSurfaceSelection);
    } else {
        renderer.domElement.removeEventListener('click', handleSurfaceSelection);
    }
}

// 清除表面选择
function clearSelection() {
    // 移除所有高亮材质
    for (const mesh of selectedMeshes) {
        if (mesh.originalMaterial) {
            mesh.material = mesh.originalMaterial;
            delete mesh.originalMaterial;
        }
    }
    
    // 清空选择数组
    selectedMeshes = [];
    selectedFaces.clear();
    
    console.log('已清除所有选择');
    
    // 更新UI
    updateSelectionCount();
}

// 处理表面选择
function handleSurfaceSelection(event) {
    event.preventDefault();
    
    // 计算鼠标位置（归一化设备坐标 -1 到 +1）
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    
    // 更新射线
    raycaster.setFromCamera(mouse, camera);
    
    // 获取射线与模型相交的物体
    const intersects = raycaster.intersectObject(model, true);
    
    if (intersects.length > 0) {
        // 获取第一个相交的物体
        const intersect = intersects[0];
        const selectedObject = intersect.object;
        
        // 只处理Mesh对象
        if (selectedObject.isMesh) {
            console.log('选中物体:', selectedObject.name || 'unnamed mesh');
            
            // 保存原始材质（如果尚未保存）
            if (!selectedObject.originalMaterial) {
                selectedObject.originalMaterial = selectedObject.material.clone();
            }
            
            // 检查该网格是否已被选中
            const index = selectedMeshes.findIndex(m => m.uuid === selectedObject.uuid);
            
            if (index === -1) {
                // 如果尚未选中，添加到选中列表并高亮显示
                selectedObject.material = highlightMaterial.clone();
                selectedMeshes.push(selectedObject);
                console.log('添加到选择');
            } else {
                // 如果已选中，从列表中移除并恢复原始材质
                selectedObject.material = selectedObject.originalMaterial;
                delete selectedObject.originalMaterial;
                selectedMeshes.splice(index, 1);
                console.log('从选择中移除');
            }
            
            // 更新选中计数
            updateSelectionCount();
        }
    }
}

// 更新选中计数
function updateSelectionCount() {
    const statusElement = document.getElementById('selection-status');
    if (statusElement) {
        statusElement.textContent = `选择模式: ${selectionMode ? '开启' : '关闭'} (已选择 ${selectedMeshes.length} 个表面)`;
    }
}

// 体素化选中的表面
function voxelizeSelectedSurface() {
    console.log('开始体素化选中表面...');
    
    if (selectedMeshes.length === 0) {
        console.warn('没有选中的表面');
        return;
    }
    
    // 获取结果显示元素
    const surfaceArea = document.getElementById('surface-area');
    
    // 计算所有选中表面的包围盒
    const boundingBox = new THREE.Box3();
    
    // 为每个选中的网格贡献到包围盒
    for (const mesh of selectedMeshes) {
        const meshBox = new THREE.Box3().setFromObject(mesh);
        boundingBox.union(meshBox);
    }
    
    // 确保包围盒有效
    if (!isBoxValid(boundingBox)) {
        console.error('选中表面的包围盒无效，无法体素化');
        if (surfaceArea) {
            surfaceArea.textContent = '无效选择 - 无法计算';
        }
        return;
    }
    
    const selectedSize = new THREE.Vector3();
    boundingBox.getSize(selectedSize);
    
    console.log('选中表面尺寸:', selectedSize);
    console.log('体素大小:', voxelSize);

    // 确保体素大小适合模型
    const minModelDim = Math.min(selectedSize.x, selectedSize.y, selectedSize.z);
    if (voxelSize > minModelDim / 2) {
        // 体素过大，自动调整
        voxelSize = minModelDim / 5;
        console.log(`体素大小过大，自动调整为: ${voxelSize.toFixed(4)}`);
    }

    // 初始化体素网格
    const gridSizeX = Math.max(2, Math.ceil(selectedSize.x / voxelSize));
    const gridSizeY = Math.max(2, Math.ceil(selectedSize.y / voxelSize));
    const gridSizeZ = Math.max(2, Math.ceil(selectedSize.z / voxelSize));

    // voxelGrid[x][y][z] = true 表示该体素被占据
    const voxelGrid = new Array(gridSizeX).fill(null)
                        .map(() => new Array(gridSizeY).fill(null)
                        .map(() => new Array(gridSizeZ).fill(false)));

    console.log(`网格尺寸: ${gridSizeX}x${gridSizeY}x${gridSizeZ}`);
    
    let triangleCount = 0;
    let processedTriangles = 0;
    let invalidTriangles = 0;
    
    // 使用体素采样方法
    console.log('采用体素采样方法进行体素化...');
    
    // 对每个选中的网格进行处理
    for (const selectedMesh of selectedMeshes) {
        const geometry = selectedMesh.geometry;
        
        // 确保几何体已处理
        geometry.computeBoundingBox();
        if (!geometry.attributes.normal) {
            geometry.computeVertexNormals();
        }
        
        // 采样方法：对模型的每个点进行体素化
        const positions = geometry.attributes.position;
        const matrixWorld = selectedMesh.matrixWorld;
        
        for (let i = 0; i < positions.count; i++) {
            const vertex = new THREE.Vector3().fromBufferAttribute(positions, i);
            vertex.applyMatrix4(matrixWorld); // 转换到世界坐标
            
            // 计算该顶点对应的体素坐标
            const voxelX = Math.floor((vertex.x - boundingBox.min.x) / voxelSize);
            const voxelY = Math.floor((vertex.y - boundingBox.min.y) / voxelSize);
            const voxelZ = Math.floor((vertex.z - boundingBox.min.z) / voxelSize);
            
            // 检查是否在有效范围内
            if (voxelX >= 0 && voxelX < gridSizeX &&
                voxelY >= 0 && voxelY < gridSizeY &&
                voxelZ >= 0 && voxelZ < gridSizeZ) {
                voxelGrid[voxelX][voxelY][voxelZ] = true;
            }
        }
        
        // 对三角形的边和内部进行采样
        if (geometry.index) {
            const indices = geometry.index.array;
            
            for (let i = 0; i < indices.length; i += 3) {
                const idx1 = indices[i];
                const idx2 = indices[i + 1];
                const idx3 = indices[i + 2];
                
                // 获取三角形的三个顶点
                const v1 = new THREE.Vector3().fromBufferAttribute(positions, idx1);
                const v2 = new THREE.Vector3().fromBufferAttribute(positions, idx2);
                const v3 = new THREE.Vector3().fromBufferAttribute(positions, idx3);
                
                // 转换到世界坐标
                v1.applyMatrix4(matrixWorld);
                v2.applyMatrix4(matrixWorld);
                v3.applyMatrix4(matrixWorld);
                
                // 在三角形边上进行采样
                sampleLine(v1, v2, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                sampleLine(v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                sampleLine(v3, v1, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                
                // 在三角形内部进行采样
                sampleTriangleInterior(v1, v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                
                triangleCount++;
                processedTriangles++;
            }
        } else {
            // 非索引几何体
            for (let i = 0; i < positions.count; i += 3) {
                if (i + 2 < positions.count) {
                    const v1 = new THREE.Vector3().fromBufferAttribute(positions, i);
                    const v2 = new THREE.Vector3().fromBufferAttribute(positions, i + 1);
                    const v3 = new THREE.Vector3().fromBufferAttribute(positions, i + 2);
                    
                    // 转换到世界坐标
                    v1.applyMatrix4(matrixWorld);
                    v2.applyMatrix4(matrixWorld);
                    v3.applyMatrix4(matrixWorld);
                    
                    // 在三角形边上进行采样
                    sampleLine(v1, v2, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                    sampleLine(v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                    sampleLine(v3, v1, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                    
                    // 在三角形内部进行采样
                    sampleTriangleInterior(v1, v2, v3, boundingBox, voxelGrid, voxelSize, gridSizeX, gridSizeY, gridSizeZ);
                    
                    triangleCount++;
                    processedTriangles++;
                }
            }
        }
    }
    
    console.log(`处理了 ${processedTriangles} 个三角形，共 ${triangleCount} 个`);
    if (invalidTriangles > 0) {
        console.warn(`发现 ${invalidTriangles} 个无效三角形`);
    }
    
    // 检查是否有任何体素被标记
    let markedVoxels = 0;
    for (let x = 0; x < gridSizeX; x++) {
        for (let y = 0; y < gridSizeY; y++) {
            for (let z = 0; z < gridSizeZ; z++) {
                if (voxelGrid[x][y][z]) {
                    markedVoxels++;
                }
            }
        }
    }
    
    console.log(`被标记的体素数量: ${markedVoxels}`);
    
    if (markedVoxels === 0) {
        // 如果没有体素被标记，尝试更小的体素大小
        if (voxelSize > 0.05) {
            console.warn('没有体素被标记，尝试更小的体素大小...');
            voxelSize = voxelSize / 2;
            if (surfaceArea) {
                surfaceArea.textContent = '重新计算中...';
            }
            setTimeout(() => {
                voxelizeSelectedSurface();
            }, 10);
            return;
        } else {
            console.error('体素化失败：没有体素被标记');
            if (surfaceArea) {
                surfaceArea.textContent = '计算失败 - 选中区域可能有问题';
            }
            return;
        }
    }

    // 识别表面体素并计算表面积
    const voxelFaceArea = voxelSize * voxelSize;
    const surfaceVoxelsMaterial = new THREE.MeshBasicMaterial({ 
        color: 0x00ff00, 
        wireframe: true,
        transparent: true,
        opacity: 0.7
    });

    totalSurfaceArea = 0; // 重置表面积计算
    let surfaceVoxelCount = 0;
    
    for (let x = 0; x < gridSizeX; x++) {
        for (let y = 0; y < gridSizeY; y++) {
            for (let z = 0; z < gridSizeZ; z++) {
                if (voxelGrid[x][y][z]) {
                    // 检查六个邻居
                    const neighbors = [
                        [x + 1, y, z], [x - 1, y, z],
                        [x, y + 1, z], [x, y - 1, z],
                        [x, y, z + 1], [x, y, z - 1]
                    ];

                    let isSurfaceVoxel = false;
                    let exposedFaces = 0;
                    for (const [nx, ny, nz] of neighbors) {
                        if (
                            nx < 0 || nx >= gridSizeX ||
                            ny < 0 || ny >= gridSizeY ||
                            nz < 0 || nz >= gridSizeZ ||
                            !voxelGrid[nx][ny][nz] // 如果邻居是空的
                        ) {
                            exposedFaces++;
                            isSurfaceVoxel = true; // 只要有一个面暴露，就认为是表面体素
                        }
                    }
                    
                    totalSurfaceArea += exposedFaces * voxelFaceArea;

                    if (isSurfaceVoxel) { // 可视化表面体素
                        surfaceVoxelCount++;
                        const voxelGeometry = new THREE.BoxGeometry(voxelSize, voxelSize, voxelSize);
                        const voxelMesh = new THREE.Mesh(voxelGeometry, surfaceVoxelsMaterial);
                        voxelMesh.position.set(
                            boundingBox.min.x + (x + 0.5) * voxelSize,
                            boundingBox.min.y + (y + 0.5) * voxelSize,
                            boundingBox.min.z + (z + 0.5) * voxelSize
                        );
                        voxelMesh.userData.isVoxel = true; // 标记为体素，方便后续清除
                        scene.add(voxelMesh);
                    }
                }
            }
        }
    }
    
    console.log(`表面体素数量: ${surfaceVoxelCount}`);
    console.log(`计算出的表面积: ${totalSurfaceArea.toFixed(4)}`);

    // 更新界面显示
    if (surfaceArea) {
        surfaceArea.textContent = `${totalSurfaceArea.toFixed(4)} 单位² (选中${selectedMeshes.length}个表面)`;
    }
}